package com.yeyks.commonReference.service.vip.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yeyks.account.dal.domain.AccountInfo;
import com.yeyks.account.utils.AccountUtil;
import com.yeyks.common.base.Arguments;
import com.yeyks.common.base.PageResult;
import com.yeyks.common.em.accountinfo.AccountInfoTypeEnum;
import com.yeyks.common.em.vip.MiniVipCommissionBillOperatorTypeEnum;
import com.yeyks.common.param.commission.MiniCommissionRecordParam;
import com.yeyks.common.result.commission.MiniCommissionRecordResult;
import com.yeyks.common.utils.RedisUtil;
import com.yeyks.commonReference.service.vip.MiniVipCommissionBillService;
import com.yeyks.commonReference.service.vip.MiniVipCommissionOverviewService;
import com.yeyks.vip.dal.domain.MiniVipCommissionBill;
import com.yeyks.vip.dal.dao.MiniVipCommissionBillMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yeyks.vip.dal.domain.MiniVipCommissionOverview;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;


/**
 * <p>
 * 精选vip订单分佣明细表 服务实现类
 * </p>
 *
 * @author shuai
 * @since 2019-09-18
 */
@Slf4j
@Service
public class MiniVipCommissionBillServiceImpl extends ServiceImpl<MiniVipCommissionBillMapper, MiniVipCommissionBill> implements MiniVipCommissionBillService {

    @Autowired
    private MiniVipCommissionOverviewService miniVipCommissionOverviewService;
    @Autowired
    private RedisUtil redisUtil;

    private static final String redisRemainDesc = "redisLock:MiniVipCommissionBillService:remainDesc";
    private static final String redisRemainAdd = "redisLock:MiniVipCommissionBillService:remainAdd";

    /**
     * 精选vip订单佣金入账
     *
     * @param accountId 账户id
     * @param amount    金额
     * @param orderNo   订单号
     * @param type      类型 1:卡酒店 2:非卡酒店
     * @param cardNo    卡号
     * @param phone     卡对应用户手机号
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void orderAdd(Integer accountId, Integer amount, String orderNo, Integer type, String cardNo, String phone) {
        if (null == amount || amount < 0) {
            amount = 0;
        }
        //获取vip分佣账户
        MiniVipCommissionOverview vipCommissionOverview = miniVipCommissionOverviewService.selectByAccountId(accountId);
        Date date = new Date();
        vipCommissionOverview.setTotalInAmount(vipCommissionOverview.getTotalInAmount() + amount);
        vipCommissionOverview.setRemainAmount(vipCommissionOverview.getRemainAmount() + amount);
        vipCommissionOverview.setUpdateTime(date);
        Arguments.isFalse(miniVipCommissionOverviewService.updateById(vipCommissionOverview), "修改小vip佣金账户表异常");
        //写入账户明细表信息
        insertBill(date, accountId,
                type, cardNo,
                MiniVipCommissionBillOperatorTypeEnum.IN.value(),
                MiniVipCommissionBillOperatorTypeEnum.IN.desc(),
                amount, orderNo, phone);
    }

    /**
     * 精选vip佣金提现
     *
     * @param accountId 账户id
     * @param amount    金额
     * @param orderNo   订单号
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void remainDesc(Integer accountId, Integer amount, String orderNo) {
        redisUtil.runWithLock(redisRemainDesc, () -> {
            Arguments.intIsNull(amount, "提现金额不能为空");
            Arguments.intEqualZero(amount, "提现金额不能为0");
            Arguments.intLtZero(amount, "提现金额有误");
            //获取vip分佣账户
            MiniVipCommissionOverview vipCommissionOverview = miniVipCommissionOverviewService.selectByAccountId(accountId);
            Arguments.isTrue(null == vipCommissionOverview.getRemainAmount()
                    || vipCommissionOverview.getRemainAmount() < amount, "账户剩余金额不足");
            Arguments.isFalse(amount.equals(vipCommissionOverview.getRemainAmount()), "必须全部提现");
            Date date = new Date();
            //首先修改账户总览表的数据
            vipCommissionOverview.setTotalOutAmount(vipCommissionOverview.getTotalOutAmount() + amount);
            vipCommissionOverview.setRemainAmount(vipCommissionOverview.getRemainAmount() - amount);
            vipCommissionOverview.setUpdateTime(date);
            Arguments.isFalse(miniVipCommissionOverviewService.updateById(vipCommissionOverview), "修改小vip佣金账户表异常");
            //写入账户明细表信息
            insertBill(date, accountId,
                    null, null,
                    MiniVipCommissionBillOperatorTypeEnum.OUT.value(),
                    MiniVipCommissionBillOperatorTypeEnum.OUT.desc(),
                    amount, orderNo, null);
            return null;
        });
    }

    /**
     * 精选vip佣金提现拒绝或失败余额回退
     *
     * @param orderNo
     * @param remark
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void remainAdd(String orderNo, String remark) {
        redisUtil.runWithLock(redisRemainAdd, () -> {
            log.info("小vip佣金提现拒绝或失败余额回退的订单号为orderNo = {}", orderNo);
            Arguments.strIsNull(orderNo, "提现订单号为空");
            MiniVipCommissionBill bill = baseMapper.selectOne(new QueryWrapper<MiniVipCommissionBill>()
                    .eq(MiniVipCommissionBill.ORDER_NO, orderNo)
                    .eq(MiniVipCommissionBill.OPERATOR_TYPE, MiniVipCommissionBillOperatorTypeEnum.OUT.value())
                    .eq(MiniVipCommissionBill.REMARK, MiniVipCommissionBillOperatorTypeEnum.OUT.desc()));
            Arguments.beanIsNull(bill, "该提现订单明细不存在");
            Date date = new Date();
            MiniVipCommissionOverview overview = miniVipCommissionOverviewService.selectByAccountId(bill.getAccountId());
            overview.setTotalOutAmount(overview.getTotalOutAmount() - bill.getOperatorAmount());
            overview.setRemainAmount(overview.getRemainAmount() + bill.getOperatorAmount());
            overview.setUpdateTime(date);
            Arguments.isFalse(miniVipCommissionOverviewService.updateById(overview), "修改小vip佣金账户表异常");
            //写入账户明细表信息
            insertBill(date, bill.getAccountId(), null, null,
                    MiniVipCommissionBillOperatorTypeEnum.FAIL.value(),
                    MiniVipCommissionBillOperatorTypeEnum.FAIL.desc(), bill.getOperatorAmount(), bill.getOrderNo(), bill.getPhone());
            return null;
        });
    }

    /**
     * 本酒店佣金记录
     *
     * @param loginUser
     * @param param
     * @return
     */
    @Override
    public PageResult<MiniCommissionRecordResult> mineCommissionList(AccountInfo loginUser, MiniCommissionRecordParam param) {
        List<Integer> typeLists = Lists.newArrayList(1, 5, 20, 22);
        Arguments.isFalse(typeLists.contains(loginUser.getType()), "您无权调用");
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        Map<String, Object> map = Maps.newHashMap();
        if (!AccountInfoTypeEnum.Administrator.value().equals(loginUser.getType())) {
            map.put("accountId", AccountUtil.getOperationUserId(loginUser));
            if (null != param.getOperatorType() && 1 == param.getOperatorType()) {
                List<Integer> types = Lists.newArrayList();
                if (AccountInfoTypeEnum.HotelManager.value().equals(loginUser.getType())) {
                    if (null == param.getType()) {
                        types.add(1);
                        types.add(5);
                    } else {
                        if (1 == param.getType()) {
                            types.add(1);
                        } else {
                            types.add(5);
                        }
                    }
                }
                if (AccountInfoTypeEnum.MiniOperateMerchant.value().equals(loginUser.getType())) {
                    if (null == param.getType()) {
                        types.add(2);
                        types.add(6);
                    } else {
                        if (1 == param.getType()) {
                            types.add(2);
                        } else {
                            types.add(6);
                        }
                    }
                }
                if (AccountInfoTypeEnum.MiniVipCardMerchant.value().equals(loginUser.getType())) {
                    types.add(9);
                }
                map.put("types", types);
            }
        }
        map.put("operatorType", param.getOperatorType());
        List<MiniCommissionRecordResult> miniCommissionRecordResultList = baseMapper.mineCommissionList(map);
        return PageResult.getPageResult(miniCommissionRecordResultList);
    }

    /**
     * 通过账户类型获取vip分佣金额
     *
     * @param commissionTypes 佣金账户类型
     * @param accountId       账户id
     * @param orderNo         订单号
     * @return
     */
    @Override
    public Integer getVipCommissionAmount(Integer accountId, String orderNo, List<Integer> commissionTypes) {
        List<MiniVipCommissionBill> miniVipCommissionBills = baseMapper.selectList(new QueryWrapper<MiniVipCommissionBill>()
                .eq(MiniVipCommissionBill.ACCOUNT_ID, accountId)
                .eq(MiniVipCommissionBill.ORDER_NO, orderNo)
                .eq(MiniVipCommissionBill.OPERATOR_TYPE, 1)
                .in(MiniVipCommissionBill.TYPE, commissionTypes));
        if (CollectionUtil.isEmpty(miniVipCommissionBills)) {
            return null;
        }
        return miniVipCommissionBills.stream().mapToInt(MiniVipCommissionBill::getOperatorAmount).sum();
    }

    /**
     * 生成明细
     *
     * @param date         创建时间
     * @param accountId    账户id
     * @param type         账户类型
     * @param cardNo       卡号
     * @param operatorType 操作类型
     * @param remark       操作类型备注
     * @param amount       操作金额
     * @param orderNo      订单号
     */
    private void insertBill(Date date, Integer accountId, Integer type, String cardNo, Integer operatorType, String remark, Integer amount, String orderNo, String phone) {
        //写入账户明细表信息
        MiniVipCommissionBill newBill = new MiniVipCommissionBill();
        newBill.setCreateTime(date);
        newBill.setAccountId(accountId);
        newBill.setRemark(remark);
        newBill.setCardNo(cardNo);
        newBill.setType(type);
        newBill.setOperatorType(operatorType);
        newBill.setOperatorAmount(amount);
        newBill.setOrderNo(orderNo);
        newBill.setPhone(phone);
        Arguments.isTrue(baseMapper.insert(newBill) != 1, "插入小vip佣金账户明细异常");
    }
}
